import React, {useEffect, useMemo, useRef, useState} from "react";
import {View, ScrollView, Text, Image, Input} from "@tarojs/components";
import Page from "@/components/page";
import PageNav from "@/components/pageNav";
import account from "@/store/account";
import user from "@/store/user";
import {defaultAvatarUrl, ShowToast, ToPage, uuid, VibrateShort} from "@/utils";
import Taro from "@tarojs/taro";
import moment from "moment";
import {MoneyFormat} from "@/utils/format";
import VoiceRecorder from "@/pages/home/billInsert/voice-recorder";
import {uploadFile} from "@/request/upload";
import http from "@/request";
import categorys from "@/store/categorys";
import {observer} from "mobx-react";
import viewMode from "@/store/viewMode";
import { eventBus } from "@/event-bus";
import { billType } from "@/types";

import "./index.scss"

interface chatType {
    accountId?: number;
    text: string;
    mine: boolean;
    id?: number | string;
    addTime: string;
    // 是否为AI
    robot?: boolean,
    amount?: number;
    // 0支出1收入
    type?: 0 | 1 | 'text';
    category?: number;
    categoryName?: string;
    date?: string;
    // 账单备注
    note?: string;
}

const aiAvatarUrl = 'https://study-plans-file.oss-cn-chengdu.aliyuncs.com/project/avatar.png'

const ChatPage: React.FC = observer(() => {
    const [scrollTopval, setScrollTopval] = useState(0);
    const [displayNum, setDisplayNum] = useState(10);
    const [isNoMore, setIsNoMore] = useState(false);
    const [vcLoading, setVcLoading] = useState(false);
    const [addLoading, setAddLoading] = useState(false);
    const [isIOS, setIsIOS] = useState(false);
    const [userInput, setUserInput] = useState('');
    // 是否为键盘输入
    const [isKeyboard, setIsKeyboard] = useState(false);
    // 录音是否可见
    const [voiceRecorderVisible, setVoiceRecorderVisible] = useState(false)
    const [location, setLocation] = useState<{ clientX: number, clientY: number } | null>({clientX: 0, clientY: 0})
    const [chatList, setChatList] = useState<chatType[]>([]);

    useEffect(() => {
        viewMode.setBehind(voiceRecorderVisible)
    }, [voiceRecorderVisible]);
    const refRecord = useRef<{
        start: () => void,
        stop: () => void
    }>({
        start: () => {
        },
        stop: () => {
        }
    })

    const scrollHeight = useMemo(() => {
        const {windowHeight, safeArea} = Taro.getWindowInfo();
        const paddingBottom = isIOS ? 0 : 20;
        return (safeArea?.height || windowHeight) - 90 - paddingBottom
    }, [isIOS])

    const scrollTop = () => {
        if (displayNum < chatList.length) {
            setDisplayNum(val => val + 10);
            setIsNoMore(false)
        } else {
            setIsNoMore(chatList.length > 10)
        }
    }
    const displayList = useMemo(() => {
        return chatList.slice(0, displayNum).filter(item => {
            return item.accountId === account.activeAccount?.id || !item.accountId
        })
    }, [chatList, displayNum])
    const hanldeLongpress = (item) => {
        VibrateShort()
        Taro.showModal({
            title: '是否删除所选记录？',
            content: '删除记录不会影响账单数据',
            success: (res: any) => {
                if (res.confirm) {
                    let list = chatList.filter(chatItem => chatItem.id !== item.id)
                    setChatList(list)
                    Taro.setStorageSync(`chat-list-${user.info?.id}`, list)
                }
            }
        })
    }

    const editBill = (item) => {
        ToPage(`/pages/bills/detail/index?id=${item.id}`)
    }

    const sayHello = () => {
        setChatList(list => [{
            robot: true,
            mine: false,
            id: uuid(),
            type: 'text',
            text: '你好，请问有什么要记录的吗',
            accountId: account.activeAccount?.id,
            addTime: moment().format('YYYY-MM-DD HH:mm:ss')
        }, ...list])
    }

    const startRecord = () => {
        VibrateShort()
        refRecord.current.start()
        setVoiceRecorderVisible(true)
        // 重置位置
        setLocation(null)
    }
    const handleMove = (e) => {
        const {clientX, clientY} = e.touches[0]
        if (voiceRecorderVisible) {
            setLocation({clientX, clientY})
        }
    }
    const recordEnd = () => {
        setVoiceRecorderVisible(false)
        refRecord.current.stop()
    }
    const recordFinish = (tempFilePath) => {
        const vcUrl = {
            // 讯飞
            xf: '/vc/voiceToText',
            // 阿里
            ali: '/vc/aliVoiceToText'
        }
        setVcLoading(true)
        uploadFile(vcUrl.xf, tempFilePath).then(res => {
            if (!res.data) {
                ShowToast('未识别到内容，请手动输入')
            } else {
                addBills(res.data || '买西瓜五块钱')
            }
        }).catch(_ => {
            ShowToast('语音识别失败，请重试')
        }).finally(() => {
            setVcLoading(false)
        })
    }
    const typeChange = () => {
        setIsKeyboard(val => !val)
        Taro.setStorageSync(`chat-type-${user.info?.id}`, !isKeyboard)
    }
    const addBills = (text: string) => {
        if (!text) {
            setAddLoading(false)
            ShowToast('输入不可为空哦')
            return
        }
        const chatItem: chatType = {
            mine: true,
            id: uuid(),
            type: 'text',
            text,
            accountId: account.activeAccount?.id,
            addTime: moment().format('YYYY-MM-DD HH:mm:ss')
        }
        let list = [chatItem, ...chatList]
        setChatList(list)
        setScrollTopval(Math.random())
        Taro.setStorageSync(`chat-list-${user.info?.id}`, list)
        // 清空输入框
        setUserInput("")
        setAddLoading(true)
        http.post('/bills/addBillChat', {
            accountId: account.activeAccount?.id,
            text,
            date: moment().format('YYYY-MM-DD')
        }).then(res => {
            if (res.data) {
                const billChatItem: chatType = {
                    ...res.data,
                    mine: false,
                    accountId: account.activeAccount?.id,
                    addTime: moment().format('YYYY-MM-DD HH:mm:ss')
                }
                list = [billChatItem, ...list]
                Taro.setStorageSync(`chat-list-${user.info?.id}`, list)
                setChatList(list)
                eventBus.emit('refreshBillListEvent');
                sendMessage(res.data)
            }
        }).catch(err => {
            const billChatItem: chatType = {
                mine: false,
                id: uuid(),
                type: 'text',
                accountId: account.activeAccount?.id,
                text: err.msg || '语义解析失败了，点击此处手动创建',
                addTime: moment().format('YYYY-MM-DD HH:mm:ss')
            }
            list = [billChatItem, ...list]
            Taro.setStorageSync(`chat-list-${user.info?.id}`, list)
            setChatList(list)
        }).finally(() => {
            setAddLoading(false)
            setScrollTopval(Math.random())
        })
    }
    
    const sendMessage = (billInfo: billType) => {
        const receiveUserIds = (account.activeAccount?.members || []).map(item => {
            return item.userId
        }).filter(id => {
            return id && (id !== user.info?.id)
        })
        if (receiveUserIds.length) {
            const categoryName = billInfo.category && categorys.categoryMap[billInfo.category].name
            Taro.requestSubscribeMessage({
                tmplIds: ['sVAHeMtfha1SkZJRSdjwKUCeHpkMLIhIbKpVrF_nlPQ'],
                entityIds: [],
                success: () => {
                    http.post("/message/sendtemplateMsg", {
                        note: billInfo.note,
                        sendUserName: user.info?.userName,
                        receiveUserIds,
                        categoryName,
                        amount: billInfo.amount
                    })
                },
                fail: (e) => {
                    console.log(e);
                }
            })
        }
    }

    Taro.useLoad((params) => {
        // 输入类型
        setIsKeyboard(!!Taro.getStorageSync(`chat-type-${user.info?.id}`))
        // 记账记录
        const storeList = (Taro.getStorageSync(`chat-list-${user.info?.id}`) || []).filter((item) => !item.robot)
        chatList.push(...storeList)
        setChatList(storeList)
        // 首页长按过来的直接添加
        if (params.text) {
            addBills(params.text)
        } else {
            sayHello()
        }
        const sysInfo = Taro.getDeviceInfo()
        const platform = sysInfo.platform.toLowerCase();
        setIsIOS(['ios', 'devtools'].includes(platform))
    })

    return (
        <Page className={`chat-page flex-column flex-item ${viewMode.isNight ? 'is-night' : 'is-day'}`}>
            <PageNav showBack className="text-color card-ground-color need-filter flex-column flex-item">
                <View className="flex1">AI助理</View>
            </PageNav>
            <View className="page-body need-filter flex-column text-color flex1">
                <ScrollView
                    showScrollbar={false}
                    lowerThreshold={100}
                    scrollTop={scrollTopval}
                    scrollY
                    enableFlex
                    onScrollToLower={scrollTop}
                    style={{height: `${scrollHeight}px`}}
                    className="chat-list flex-column">
                    {displayList.length < 10 ? <View className="flex1 nihao"></View> : null}
                    {addLoading || vcLoading ? <View className="flex-row chat-item">
                        <View className="flex1"></View>
                        <View className="content font-size26 left card-ground-color">
                            {vcLoading ? <Text>语音识别中</Text> : null}
                            {addLoading ? <Text>请稍候，小的分析中</Text> : null}
                            <Text className="dot">.</Text>
                            <Text className="dot">.</Text>
                            <Text className="dot">.</Text>
                            <View className="triangle">&#9660;</View>
                        </View>
                        <Image className="chat-avatar-img" src={aiAvatarUrl} mode="heightFix"></Image>
                    </View> : null}
                    {
                        displayList.map(item => {
                            return (
                                <>
                                    {item.type === 'text' ?
                                        <View key={item.id} className="flex-row chat-item"
                                              onLongPress={() => hanldeLongpress(item)}>
                                            {item.mine ?
                                                <Image className="chat-avatar-img" src={user.info?.avatarUrl || defaultAvatarUrl} mode="heightFix"></Image> :
                                                <View v-else className="flex1"></View>
                                            }
                                            <View
                                                className={`content font-size26 flex-row flex-item card-ground-color ${item.mine ? 'right' : 'left'}`}>
                                                <Text>{item.text}</Text>
                                                <View className="triangle">&#9660;</View>
                                                {item.mine ? <Text className="add-time font-size16">{item.addTime}</Text> : null}
                                            </View>
                                            {
                                                item.mine ?
                                                    <View className="flex1"></View> :
                                                    <Image src={aiAvatarUrl} mode="heightFix" className="chat-avatar-img"></Image>
                                            }
                                        </View> :
                                        <View key={item.id} className="flex-row chat-item" onLongPress={() => hanldeLongpress(item)}>
                                            <View className="flex1"></View>
                                            <View className="content font-size26 left bill-card card-ground-color">
                                                <View className="title font-size28 flex-row flex-item flex1">
                                                    <Text>已记账</Text>
                                                    <View className="flex1"></View>
                                                    <Text onClick={() => editBill(item)}
                                                          className={`font-size36 amount ${item.type ? 'income' : ''}`}>
                                                        {item.type === 1 ? '+' : item.type === 0 ? '-' : ''}{MoneyFormat(item.amount)}
                                                    </Text>
                                                    <Text onClick={() => editBill(item)} className="icon-btn font-size36 iconfont icon-bianji"></Text>
                                                </View>
                                                <View className="card-body">
                                                    <View className="info-item">
                                                        <Text className="iconfont">&#xe621;</Text>
                                                        <Text>{item.category && categorys.categoryMap ? categorys.categoryMap[item.category].name : '-'}</Text>
                                                    </View>
                                                    <View className="info-item">
                                                        <Text className="iconfont">&#xe673;</Text>
                                                        <Text>{moment(item.date).format('YYYY-MM-DD')}</Text>
                                                    </View>
                                                    <View className="info-item font-otw">
                                                        <Text className="iconfont">&#xe697;</Text>
                                                        <Text>{item.note}</Text>
                                                    </View>
                                                </View>
                                                <View className="triangle">&#9660;</View>
                                            </View>
                                            <Image className="chat-avatar-img" src={aiAvatarUrl} mode="heightFix"></Image>
                                        </View>
                                    }
                                </>
                            )
                        })
                    }
                    { isNoMore ? <view className="chat-no-more">没有更多记录了</view> : null}
                </ScrollView>
                {/*<View className="flex1"></View>*/}
                <View className="page-bottom-container flex-column flex-item card-ground-color flex1">
                    <View className="input-box flex-row flex-item">
                        {
                            isKeyboard ?
                                <>
                                    <Text onClick={() => setIsKeyboard(val => !val)} className="iconfont icon-jianpan"></Text>
                                    <Input type="text"
                                           placeholder-class="placeholder-style"
                                           className="flex1 input"
                                           value={userInput}
                                           placeholder="请输入"
                                           onInput={e => setUserInput(e.detail.value)} cursorSpacing={isIOS ? 80 : 30}
                                           alwaysEmbed>
                                    </Input>
                                </> :
                                <>
                                    <Text onClick={typeChange} className="iconfont icon-yuyin2"></Text>
                                    <View onTouchStart={startRecord}
                                          onTouchMove={handleMove}
                                          onTouchEnd={recordEnd}
                                          className="flex1 input flex-row flex-center">
                                        <Text>按住 说话</Text>
                                    </View>
                                </>
                        }
                        <View onClick={() => addBills(userInput)} className="submit-btn flex-row flex-center">
                            <Text className="btn-text font-size26">发 送</Text>
                        </View>
                    </View>
                    <View className="flex1"></View>
                </View>
            </View>
            <VoiceRecorder
                ref={refRecord}
                visible={voiceRecorderVisible}
                onFinish={recordFinish}
                location={location}></VoiceRecorder>
        </Page>
    )
})
export default ChatPage